add new marshallers used by the text widget
authorHavoc Pennington <hp@redhat.com>
Thu, 26 Oct 2000 23:05:43 +0000 (23:05 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Thu, 26 Oct 2000 23:05:43 +0000 (23:05 +0000)
2000-10-26  Havoc Pennington  <hp@redhat.com>

* gtk/gtkmarshal.list: add new marshallers used by the text widget

* gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
types

* gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
marshaller types

* gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
license on these files.

* gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
work.

* gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to
runtime random number different for each tree, instead of
a constant I made up.

21 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkmarshal.list
gtk/gtkmarshalers.list
gtk/gtktextbtree.c
gtk/gtktextbuffer.c
gtk/gtktextdisplay.c
gtk/gtktextdisplay.h
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktextlayout.c
gtk/gtktextlayout.h
gtk/gtktexttagtable.c
gtk/gtktextview.c
gtk/testtext.c
tests/testtext.c

index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 81d80908efd3673345995150c8153ccb3da5d691..0656e8624a1d96a2fd4bef64a672dc6d5618d254 100644 (file)
@@ -1,3 +1,24 @@
+2000-10-26  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtkmarshal.list: add new marshallers used by the text widget
+
+       * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller
+       types
+
+       * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix
+       marshaller types
+
+       * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h,
+       gtk/gtktextdisplay.c: We need to preserve Tk copyrights and
+       license on these files.
+
+       * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this
+       work.
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to 
+       runtime random number different for each tree, instead of 
+       a constant I made up.
+
 Thu Oct 26 07:36:16 2000  Tim Janik  <timj@gtk.org>
 
        * gtk/Makefile.am: buncha cleanups, kludged build sources
index 1395f1da18a3b056fa0f7ddf9b0be6be1ec19ace..bebc4ff36c1b7025e21f4292fd2fd0ba20f4a1f6 100644 (file)
@@ -49,11 +49,14 @@ VOID:INT,INT,INT,INT
 VOID:INT,INT,POINTER
 VOID:OBJECT
 VOID:POINTER
+VOID:POINTER,BOOLEAN
 VOID:POINTER,INT
 VOID:POINTER,INT,INT,POINTER,UINT,UINT
 VOID:POINTER,INT,POINTER
 VOID:POINTER,POINTER
+VOID:POINTER,POINTER,BOOLEAN
 VOID:POINTER,POINTER,INT
+VOID:POINTER,POINTER,INT,BOOLEAN
 VOID:POINTER,POINTER,INT,INT
 VOID:POINTER,POINTER,POINTER
 VOID:POINTER,POINTER,UINT,UINT
index 1395f1da18a3b056fa0f7ddf9b0be6be1ec19ace..bebc4ff36c1b7025e21f4292fd2fd0ba20f4a1f6 100644 (file)
@@ -49,11 +49,14 @@ VOID:INT,INT,INT,INT
 VOID:INT,INT,POINTER
 VOID:OBJECT
 VOID:POINTER
+VOID:POINTER,BOOLEAN
 VOID:POINTER,INT
 VOID:POINTER,INT,INT,POINTER,UINT,UINT
 VOID:POINTER,INT,POINTER
 VOID:POINTER,POINTER
+VOID:POINTER,POINTER,BOOLEAN
 VOID:POINTER,POINTER,INT
+VOID:POINTER,POINTER,INT,BOOLEAN
 VOID:POINTER,POINTER,INT,INT
 VOID:POINTER,POINTER,POINTER
 VOID:POINTER,POINTER,UINT,UINT
index 5b1f98430b72e7132143386c20e354c52020e790..59c00824e98887a58c8315e73920392bd2072bf1 100644 (file)
@@ -394,9 +394,11 @@ gtk_text_btree_new (GtkTextTagTable *table,
   tree->views = NULL;
 
   /* Set these to values that are unlikely to be found
-     in random memory garbage. */
-  tree->chars_changed_stamp = 49;
-  tree->segments_changed_stamp = 243;
+   * in random memory garbage, and also avoid
+   * duplicates between tree instances.
+   */
+  tree->chars_changed_stamp = g_random_int ();
+  tree->segments_changed_stamp = g_random_int ();
 
   tree->end_iter_line_stamp = tree->chars_changed_stamp - 1;
   tree->end_iter_line = NULL;
index 739cfe69b4030ab4faf98a87188450503fd16cfb..dc43d0389d68ed6c3e4d1ed6a108a115c7c215d5 100644 (file)
@@ -137,7 +137,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
                     GTK_RUN_LAST,
                     GTK_CLASS_TYPE (object_class),
                     GTK_SIGNAL_OFFSET (GtkTextBufferClass, insert_text),
-                    gtk_marshal_VOID__POINTER_POINTER_INT_INT,
+                    gtk_marshal_VOID__POINTER_POINTER_INT_BOOLEAN,
                     GTK_TYPE_NONE,
                     4,
                     GTK_TYPE_POINTER,
@@ -150,7 +150,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
                     GTK_RUN_LAST,
                     GTK_CLASS_TYPE (object_class),
                     GTK_SIGNAL_OFFSET (GtkTextBufferClass, delete_text),
-                    gtk_marshal_VOID__POINTER_POINTER_INT,
+                    gtk_marshal_VOID__POINTER_POINTER_BOOLEAN,
                     GTK_TYPE_NONE,
                     3,
                     GTK_TYPE_POINTER,
index d5cd2ed336a9e2c4b725396b51f4db93cdfecc60..fd0499de43a712c4aee93b81a37cc7dfd6350bd7 100644 (file)
@@ -5,6 +5,26 @@
  * Copyright (c) 2000 Red Hat, Inc.
  * Tk->Gtk port by Havoc Pennington
  *
+ * This file can be used under your choice of two licenses, the LGPL
+ * and the original Tk license.
+ * 
+ * LGPL:
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Original Tk license:
  *
  * This software is copyrighted by the Regents of the University of
  * California, Sun Microsystems, Inc., and other parties.  The
  * foregoing, the authors grant the U.S. Government and others acting
  * in its behalf permission to use and distribute the software in
  * accordance with the terms specified in this license.
- * 
+ *
+ */
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "gtktextdisplay.h"
index 84504c692a083e560057243f6c2f49054d2d6849..acbc5f9727f043f609273207214a67ca5935eefe 100644 (file)
@@ -1,6 +1,15 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+/* gtktextdisplay.c - display layed-out text
  *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Red Hat, Inc.
+ * Tk->Gtk port by Havoc Pennington
+ *
+ * This file can be used under your choice of two licenses, the LGPL
+ * and the original Tk license.
+ * 
+ * LGPL:
+ * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Original Tk license:
+ *
+ * This software is copyrighted by the Regents of the University of
+ * California, Sun Microsystems, Inc., and other parties.  The
+ * following terms apply to all files associated with the software
+ * unless explicitly disclaimed in individual files.
+ * 
+ * The authors hereby grant permission to use, copy, modify,
+ * distribute, and license this software and its documentation for any
+ * purpose, provided that existing copyright notices are retained in
+ * all copies and that this notice is included verbatim in any
+ * distributions. No written agreement, license, or royalty fee is
+ * required for any of the authorized uses.  Modifications to this
+ * software may be copyrighted by their authors and need not follow
+ * the licensing terms described here, provided that the new terms are
+ * clearly indicated on the first page of each file where they apply.
+ * 
+ * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
+ * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+ * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
+ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * GOVERNMENT USE: If you are acquiring this software on behalf of the
+ * U.S. government, the Government shall have only "Restricted Rights"
+ * in the software and related documentation as defined in the Federal
+ * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+ * are acquiring the software on behalf of the Department of Defense,
+ * the software shall be classified as "Commercial Computer Software"
+ * and the Government shall have only "Restricted Rights" as defined
+ * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
+ * foregoing, the authors grant the U.S. Government and others acting
+ * in its behalf permission to use and distribute the software in
+ * accordance with the terms specified in this license.
+ *
  */
-
 /*
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
index 32f85be9a2347a8a7a45ef9e2d4228de93e83d92..d4aefe3ef48e97f62ccdb564fc38c6dc397cd83f 100644 (file)
@@ -2172,7 +2172,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter)
 
   check_invariants(iter);
   
-  new_line = gtk_text_line_previous(real->line);
+  new_line = gtk_text_line_previous (real->line);
 
   offset_will_change = FALSE;
   if (real->line_char_offset > 0)
@@ -2182,7 +2182,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter)
     {
       real->line = new_line;
       
-      adjust_line_number(real, -1);
+      adjust_line_number (real, -1);
     }
   else
     {
@@ -2200,19 +2200,18 @@ gtk_text_iter_backward_line(GtkTextIter *iter)
   
   /* Find first segment in line */
   real->any_segment = real->line->segments;
-  real->segment = gtk_text_line_byte_to_segment(real->line,
-                                                0, &offset);
+  real->segment = gtk_text_line_byte_to_segment (real->line,
+                                                 0, &offset);
 
   g_assert(offset == 0);
 
-  /* Note that if we are on the first line, we snap to the start
-     of the first line and return TRUE, so TRUE means the
-     iterator changed, not that the line changed; this is maybe
-     a bit weird. I'm not sure there's an obvious right thing
-     to do though.
-  */
+  /* Note that if we are on the first line, we snap to the start of
+   * the first line and return TRUE, so TRUE means the iterator
+   * changed, not that the line changed; this is maybe a bit
+   * weird. I'm not sure there's an obvious right thing to do though.
+   */
 
-  check_invariants(iter);
+  check_invariants (iter);
   
   return TRUE;
 }
@@ -3048,7 +3047,20 @@ gtk_text_iter_forward_search (const GtkTextIter *iter,
   g_return_val_if_fail (str != NULL, FALSE);
 
   if (*str == '\0')
-    return TRUE; /* we found the empty string */
+    {
+      /* If we can move one char, return the empty string there */
+      match = *iter;
+      if (gtk_text_iter_next_char (&match))
+        {
+          if (match_start)
+            *match_start = match;
+          if (match_end)
+            *match_end = match;
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
   
   /* locate all lines */
 
@@ -3085,17 +3097,332 @@ gtk_text_iter_forward_search (const GtkTextIter *iter,
   return retval;
 }
 
+static gboolean
+vectors_equal_ignoring_trailing (gchar **vec1,
+                                 gchar **vec2)
+{
+  /* Ignores trailing chars in vec2's last line */
+
+  gchar **i1, **i2;
+
+  i1 = vec1;
+  i2 = vec2;
+
+  while (*i1 && *i2)
+    {      
+      if (strcmp (*i1, *i2) != 0)
+        {
+          if (*(i2 + 1) == NULL) /* if this is the last line */
+            {
+              gint len1 = strlen (*i1);
+              gint len2 = strlen (*i2);
+              
+              if (len2 >= len1 &&
+                  strncmp (*i1, *i2, len1) == 0)
+                {
+                  /* We matched ignoring the trailing stuff in vec2 */
+                  return TRUE;
+                }
+              else
+                {
+                  return FALSE;
+                }
+            }
+          else
+            {
+              return FALSE;
+            }
+        }
+      ++i1;
+      ++i2;
+    }
+
+  if (*i1 || *i2)
+    {
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+typedef struct _LinesWindow LinesWindow;
+
+struct _LinesWindow
+{
+  gint n_lines;
+  gchar **lines;
+  GtkTextIter first_line_start;
+  GtkTextIter first_line_end;
+  gboolean slice;
+  gboolean visible_only;
+};
+
+static void
+lines_window_init (LinesWindow       *win,
+                   const GtkTextIter *start)
+{
+  gint i;
+  GtkTextIter line_start;
+  GtkTextIter line_end;
+
+  /* If we start on line 1, there are 2 lines to search (0 and 1), so
+   * n_lines can be 2.
+   */  
+  if (gtk_text_iter_is_first (start) ||
+      gtk_text_iter_get_line (start) + 1 < win->n_lines)
+    {
+      /* Already at the end, or not enough lines to match */
+      win->lines = g_new0 (gchar*, 1);
+      *win->lines = NULL;
+      return;
+    }
+  
+  line_start = *start;
+  line_end = *start;
+
+  /* Move to start iter to start of line */
+  gtk_text_iter_set_line_offset (&line_start, 0);
+
+  if (gtk_text_iter_equal (&line_start, &line_end))
+    {
+      /* we were already at the start; so go back one line */
+      gtk_text_iter_backward_line (&line_start);
+    }
+  
+  win->first_line_start = line_start;
+  win->first_line_end = line_end;
+  
+  win->lines = g_new0 (gchar*, win->n_lines + 1);
+  
+  i = win->n_lines - 1;
+  while (i >= 0)
+    {
+      gchar *line_text;
+      
+      if (win->slice)
+        {
+          if (win->visible_only)
+            line_text = gtk_text_iter_get_visible_slice (&line_start, &line_end);
+          else
+            line_text = gtk_text_iter_get_slice (&line_start, &line_end);
+        }
+      else
+        {      
+          if (win->visible_only)
+            line_text = gtk_text_iter_get_visible_text (&line_start, &line_end);
+          else
+            line_text = gtk_text_iter_get_text (&line_start, &line_end);
+        }
+
+      win->lines[i] = line_text;
+
+      line_end = line_start;
+      gtk_text_iter_backward_line (&line_start);
+      
+      --i;
+    }
+}
+
+static gboolean
+lines_window_back (LinesWindow *win)
+{
+  GtkTextIter new_start;
+  gchar *line_text;
+  
+  new_start = win->first_line_start;
+
+  if (!gtk_text_iter_backward_line (&new_start))
+    return FALSE;
+  else 
+    {
+      win->first_line_start = new_start;
+      win->first_line_end = new_start;
+
+      gtk_text_iter_forward_line (&win->first_line_end);      
+    }
+
+  if (win->slice)
+    {
+      if (win->visible_only)
+        line_text = gtk_text_iter_get_visible_slice (&win->first_line_start, 
+                                                     &win->first_line_end);
+      else
+        line_text = gtk_text_iter_get_slice (&win->first_line_start, 
+                                             &win->first_line_end);
+    }
+  else
+    {      
+      if (win->visible_only)
+        line_text = gtk_text_iter_get_visible_text (&win->first_line_start, 
+                                                    &win->first_line_end);
+      else
+        line_text = gtk_text_iter_get_text (&win->first_line_start, 
+                                            &win->first_line_end);
+    }
+  
+  /* Move lines to make room for first line. */
+  g_memmove (win->lines + 1, win->lines, win->n_lines * sizeof (gchar*));
+
+  *win->lines = line_text;
+
+  /* Free old last line and NULL-terminate */
+  g_free (win->lines[win->n_lines]);
+  win->lines[win->n_lines] = NULL;
+
+  return TRUE;
+}
+
+static void
+lines_window_free (LinesWindow *win)
+{
+  g_strfreev (win->lines);
+}
+
+static gchar*
+my_strrstr (const gchar *haystack,
+            const gchar *needle)
+{
+  /* FIXME GLib should have a nice implementation in it, this
+   * is slow-ass crap.
+   */
+
+  gint haystack_len = strlen (haystack);
+  gint needle_len = strlen (needle);
+  const gchar *needle_end = needle + needle_len;
+  const gchar *haystack_rend = haystack - 1;
+  const gchar *needle_rend = needle - 1;
+  const gchar *p;
+  
+  p = haystack + haystack_len;
+  while (p != haystack)
+    {
+      const gchar *n = needle_end - 1;
+      const gchar *s = p - 1;
+      while (s != haystack_rend &&
+             n != needle_rend &&
+             *s == *n)
+        {
+          --n;
+          --s;
+        }
+
+      if (n == needle_rend)
+        return ++s;
+        
+      --p;
+    }
+
+  return NULL;
+}
+     
 gboolean
-gtk_text_iter_backward_search (GtkTextIter *iter,
-                               const char  *str,
-                               gboolean visible_only,
-                               gboolean slice)
+gtk_text_iter_backward_search (const GtkTextIter *iter,
+                               const gchar       *str,
+                               gboolean           visible_only,
+                               gboolean           slice,
+                               GtkTextIter       *match_start,
+                               GtkTextIter       *match_end)
 {
+  gchar **lines = NULL;
+  gchar **l;
+  gint n_lines;
+  LinesWindow win;
+  gboolean retval = FALSE;
+  
   g_return_val_if_fail (iter != NULL, FALSE);
   g_return_val_if_fail (str != NULL, FALSE);
 
+  if (*str == '\0')
+    {
+      /* If we can move one char, return the empty string there */
+      GtkTextIter match = *iter;
+      
+      if (gtk_text_iter_prev_char (&match))
+        {
+          if (match_start)
+            *match_start = match;
+          if (match_end)
+            *match_end = match;
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+  
+  /* locate all lines */
+
+  lines = strbreakup (str, "\n", -1);
+
+  l = lines;
+  n_lines = 0;
+  while (*l)
+    {
+      ++n_lines;
+      ++l;
+    }
+
+  win.n_lines = n_lines;
+  win.slice = slice;
+  win.visible_only = visible_only;
   
+  lines_window_init (&win, iter);
+
+  if (*win.lines == NULL)
+    goto out;
   
+  do
+    {
+      gchar *first_line_match;
+
+      /* If there are multiple lines, the first line will
+       * end in '\n', so this will only match at the
+       * end of the first line, which is correct.
+       */
+      first_line_match = my_strrstr (*win.lines, *lines);
+      
+      if (first_line_match &&  
+          vectors_equal_ignoring_trailing (lines + 1, win.lines + 1))
+          {
+            /* Match! */
+            gint offset;
+            GtkTextIter next;
+
+            /* Offset to start of search string */
+            offset = g_utf8_strlen (*win.lines, first_line_match - *win.lines);
+
+            next = win.first_line_start;
+            if (match_start)
+              {
+                *match_start = next;
+                forward_chars_with_skipping (match_start, offset,
+                                             visible_only, !slice);
+              }
+
+            /* Go to end of search string */
+            l = lines;
+            while (*l)
+              {
+                offset += g_utf8_strlen (*l, -1);
+                ++l;
+              }
+                
+            forward_chars_with_skipping (&next, offset,
+                                         visible_only, !slice);
+
+            if (match_end)
+              *match_end = next;
+            
+            retval = TRUE;
+            goto out;
+          }
+    }
+  while (lines_window_back (&win));
+
+ out:
+  lines_window_free (&win);
+  g_strfreev (lines);
+  
+  return retval;  
 }
 
 /*
@@ -3103,7 +3430,8 @@ gtk_text_iter_backward_search (GtkTextIter *iter,
  */
 
 gboolean
-gtk_text_iter_equal(const GtkTextIter *lhs, const GtkTextIter *rhs)
+gtk_text_iter_equal (const GtkTextIter *lhs,
+                     const GtkTextIter *rhs)
 {
   GtkTextRealIter *real_lhs;
   GtkTextRealIter *real_rhs;
index 9a49dfbfab99dc2e45ee700503d888b732358e94..f9b920284010ba4fcdedd3b511facf59e6efc6fa 100644 (file)
@@ -185,17 +185,20 @@ gboolean gtk_text_iter_backward_find_char     (GtkTextIter *iter,
                                               GtkTextCharPredicate pred,
                                               gpointer user_data);
 
-gboolean gtk_text_iter_forward_search         (const GtkTextIter *iter,
-                                               const gchar *str,
-                                               gboolean     visible_only,
-                                               gboolean     slice,
-                                               GtkTextIter *match_start,
-                                               GtkTextIter *match_end);
-
-gboolean gtk_text_iter_backward_search        (GtkTextIter *iter,
-                                               const char  *str,
-                                               gboolean visible_only,
-                                               gboolean slice);
+gboolean gtk_text_iter_forward_search  (const GtkTextIter *iter,
+                                        const gchar       *str,
+                                        gboolean           visible_only,
+                                        gboolean           slice,
+                                        GtkTextIter       *match_start,
+                                        GtkTextIter       *match_end);
+gboolean gtk_text_iter_backward_search (const GtkTextIter *iter,
+                                        const gchar       *str,
+                                        gboolean           visible_only,
+                                        gboolean           slice,
+                                        GtkTextIter       *match_start,
+                                        GtkTextIter       *match_end);
+
+
 
 /*
  * Comparisons
index 363aafbcad4334ccf2da631fc2971467f6b9ee48..bcb8e693d52b068e3e92317943386b6a5c385689 100644 (file)
@@ -1,4 +1,5 @@
-/* gtktextlayout.c - calculate the layout of the text
+/* GTK - The GIMP Toolkit
+ * gtktextlayout.c - calculate the layout of the text
  *
  * Copyright (c) 1992-1994 The Regents of the University of California.
  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
@@ -6,6 +7,26 @@
  * Tk->Gtk port by Havoc Pennington
  * Pango support by Owen Taylor
  *
+ * This file can be used under your choice of two licenses, the LGPL
+ * and the original Tk license.
+ * 
+ * LGPL:
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Original Tk license:
  *
  * This software is copyrighted by the Regents of the University of
  * California, Sun Microsystems, Inc., and other parties.  The
  * foregoing, the authors grant the U.S. Government and others acting
  * in its behalf permission to use and distribute the software in
  * accordance with the terms specified in this license.
- * 
+ *
+ */
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "gtksignal.h"
index 1fb499e63bb6c0e14208b160dd0b6f82797610ee..cfa7c88f4b82c8ef66915d8637a340aeddf904d8 100644 (file)
@@ -1,6 +1,17 @@
 /* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * gtktextlayout.h
  *
+ * Copyright (c) 1992-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Red Hat, Inc.
+ * Tk->Gtk port by Havoc Pennington
+ * Pango support by Owen Taylor
+ *
+ * This file can be used under your choice of two licenses, the LGPL
+ * and the original Tk license.
+ * 
+ * LGPL:
+ * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Original Tk license:
+ *
+ * This software is copyrighted by the Regents of the University of
+ * California, Sun Microsystems, Inc., and other parties.  The
+ * following terms apply to all files associated with the software
+ * unless explicitly disclaimed in individual files.
+ * 
+ * The authors hereby grant permission to use, copy, modify,
+ * distribute, and license this software and its documentation for any
+ * purpose, provided that existing copyright notices are retained in
+ * all copies and that this notice is included verbatim in any
+ * distributions. No written agreement, license, or royalty fee is
+ * required for any of the authorized uses.  Modifications to this
+ * software may be copyrighted by their authors and need not follow
+ * the licensing terms described here, provided that the new terms are
+ * clearly indicated on the first page of each file where they apply.
+ * 
+ * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
+ * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+ * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
+ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * GOVERNMENT USE: If you are acquiring this software on behalf of the
+ * U.S. government, the Government shall have only "Restricted Rights"
+ * in the software and related documentation as defined in the Federal
+ * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+ * are acquiring the software on behalf of the Department of Defense,
+ * the software shall be classified as "Commercial Computer Software"
+ * and the Government shall have only "Restricted Rights" as defined
+ * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
+ * foregoing, the authors grant the U.S. Government and others acting
+ * in its behalf permission to use and distribute the software in
+ * accordance with the terms specified in this license.
+ *
  */
-
 /*
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
index 3d3d436f2fbfe78b129826704807b24bd4846c91..c137b6c25db5e3196ba3843bf28412be61d29ce1 100644 (file)
@@ -63,7 +63,7 @@ gtk_text_tag_table_class_init (GtkTextTagTableClass *klass)
                     GTK_RUN_LAST,
                     GTK_CLASS_TYPE (object_class),
                     GTK_SIGNAL_OFFSET (GtkTextTagTableClass, tag_changed),
-                    gtk_marshal_VOID__POINTER_INT,
+                    gtk_marshal_VOID__POINTER_BOOLEAN,
                     GTK_TYPE_NONE,
                     2,
                     GTK_TYPE_OBJECT,
index bab192c873d40aac9cddfaeffc70292071482094..cb840494453666d0aead626b03abd63a935522f2 100644 (file)
@@ -835,7 +835,7 @@ set_adjustment_clamped (GtkAdjustment *adj, gfloat val)
   gtk_adjustment_set_value (adj, val);
 }
 
-gboolean
+static gboolean
 gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
                                        GtkTextMark *mark,
                                       gint margin,
index f2237d2ae481b47338aa671f980a684515db86e9..d62545f7ae7d93148f9a58a45d87c3aec76973d1 100644 (file)
@@ -47,6 +47,9 @@ static void     buffer_filename_set (Buffer *buffer);
 static void     buffer_search_forward (Buffer *buffer,
                                        const char *str,
                                        View *view);
+static void     buffer_search_backward (Buffer *buffer,
+                                       const char *str,
+                                       View *view);
 
 static View *view_from_widget (GtkWidget *widget);
 
@@ -930,6 +933,12 @@ do_apply_tabs (gpointer callback_data,
     }
 }
 
+enum
+{
+  RESPONSE_FORWARD,
+  RESPONSE_BACKWARD
+};
+
 static void
 dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
 {
@@ -937,6 +946,13 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
   View *view = data;
   GtkTextIter start, end;
   gchar *search_string;
+
+  if (response_id != RESPONSE_FORWARD &&
+      response_id != RESPONSE_BACKWARD)
+    {
+      gtk_widget_destroy (dialog);
+      return;
+    }
   
   buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer");
 
@@ -948,9 +964,12 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
   search_string = gtk_text_iter_get_text (&start, &end);
 
   printf ("Searching for `%s'\n", search_string);
-  
-  buffer_search_forward (view->buffer, search_string, view);
 
+  if (response_id == RESPONSE_FORWARD)
+    buffer_search_forward (view->buffer, search_string, view);
+  else if (response_id == RESPONSE_BACKWARD)
+    buffer_search_backward (view->buffer, search_string, view);
+    
   g_free (search_string);
   
   gtk_widget_destroy (dialog);
@@ -969,7 +988,9 @@ do_search (gpointer callback_data,
   dialog = gtk_dialog_new_with_buttons ("Search",
                                         GTK_WINDOW (view->window),
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
-                                        GTK_STOCK_BUTTON_CLOSE,
+                                        "Forward", RESPONSE_FORWARD,
+                                        "Backward", RESPONSE_BACKWARD,
+                                        GTK_STOCK_BUTTON_CANCEL,
                                         GTK_RESPONSE_NONE, NULL);
 
 
@@ -1303,8 +1324,10 @@ buffer_filename_set (Buffer *buffer)
 }
 
 static void
-buffer_search_forward (Buffer *buffer, const char *str,
-                       View *view)
+buffer_search (Buffer     *buffer,
+               const char *str,
+               View       *view,
+               gboolean forward)
 {
   GtkTextIter iter;
   GtkTextIter start, end;
@@ -1324,15 +1347,30 @@ buffer_search_forward (Buffer *buffer, const char *str,
   if (*str != '\0')
     {
       GtkTextIter match_start, match_end;
-      
-      while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
-                                           &match_start, &match_end))
-        {
-          ++i;
-          gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
-                                     &match_start, &match_end);
 
-          iter = match_end;
+      if (forward)
+        {
+          while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
+                                               &match_start, &match_end))
+            {
+              ++i;
+              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
+                                         &match_start, &match_end);
+              
+              iter = match_end;
+            }
+        }
+      else
+        {
+          while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE,
+                                                &match_start, &match_end))
+            {
+              ++i;
+              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
+                                         &match_start, &match_end);
+              
+              iter = match_start;
+            }
         }
     }
 
@@ -1351,6 +1389,20 @@ buffer_search_forward (Buffer *buffer, const char *str,
   gtk_widget_show (dialog);
 }
 
+static void
+buffer_search_forward (Buffer *buffer, const char *str,
+                       View *view)
+{
+  buffer_search (buffer, str, view, TRUE);
+}
+
+static void
+buffer_search_backward (Buffer *buffer, const char *str,
+                        View *view)
+{
+  buffer_search (buffer, str, view, FALSE);
+}
+
 static void
 buffer_ref (Buffer *buffer)
 {
index f2237d2ae481b47338aa671f980a684515db86e9..d62545f7ae7d93148f9a58a45d87c3aec76973d1 100644 (file)
@@ -47,6 +47,9 @@ static void     buffer_filename_set (Buffer *buffer);
 static void     buffer_search_forward (Buffer *buffer,
                                        const char *str,
                                        View *view);
+static void     buffer_search_backward (Buffer *buffer,
+                                       const char *str,
+                                       View *view);
 
 static View *view_from_widget (GtkWidget *widget);
 
@@ -930,6 +933,12 @@ do_apply_tabs (gpointer callback_data,
     }
 }
 
+enum
+{
+  RESPONSE_FORWARD,
+  RESPONSE_BACKWARD
+};
+
 static void
 dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
 {
@@ -937,6 +946,13 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
   View *view = data;
   GtkTextIter start, end;
   gchar *search_string;
+
+  if (response_id != RESPONSE_FORWARD &&
+      response_id != RESPONSE_BACKWARD)
+    {
+      gtk_widget_destroy (dialog);
+      return;
+    }
   
   buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer");
 
@@ -948,9 +964,12 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
   search_string = gtk_text_iter_get_text (&start, &end);
 
   printf ("Searching for `%s'\n", search_string);
-  
-  buffer_search_forward (view->buffer, search_string, view);
 
+  if (response_id == RESPONSE_FORWARD)
+    buffer_search_forward (view->buffer, search_string, view);
+  else if (response_id == RESPONSE_BACKWARD)
+    buffer_search_backward (view->buffer, search_string, view);
+    
   g_free (search_string);
   
   gtk_widget_destroy (dialog);
@@ -969,7 +988,9 @@ do_search (gpointer callback_data,
   dialog = gtk_dialog_new_with_buttons ("Search",
                                         GTK_WINDOW (view->window),
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
-                                        GTK_STOCK_BUTTON_CLOSE,
+                                        "Forward", RESPONSE_FORWARD,
+                                        "Backward", RESPONSE_BACKWARD,
+                                        GTK_STOCK_BUTTON_CANCEL,
                                         GTK_RESPONSE_NONE, NULL);
 
 
@@ -1303,8 +1324,10 @@ buffer_filename_set (Buffer *buffer)
 }
 
 static void
-buffer_search_forward (Buffer *buffer, const char *str,
-                       View *view)
+buffer_search (Buffer     *buffer,
+               const char *str,
+               View       *view,
+               gboolean forward)
 {
   GtkTextIter iter;
   GtkTextIter start, end;
@@ -1324,15 +1347,30 @@ buffer_search_forward (Buffer *buffer, const char *str,
   if (*str != '\0')
     {
       GtkTextIter match_start, match_end;
-      
-      while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
-                                           &match_start, &match_end))
-        {
-          ++i;
-          gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
-                                     &match_start, &match_end);
 
-          iter = match_end;
+      if (forward)
+        {
+          while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
+                                               &match_start, &match_end))
+            {
+              ++i;
+              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
+                                         &match_start, &match_end);
+              
+              iter = match_end;
+            }
+        }
+      else
+        {
+          while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE,
+                                                &match_start, &match_end))
+            {
+              ++i;
+              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
+                                         &match_start, &match_end);
+              
+              iter = match_start;
+            }
         }
     }
 
@@ -1351,6 +1389,20 @@ buffer_search_forward (Buffer *buffer, const char *str,
   gtk_widget_show (dialog);
 }
 
+static void
+buffer_search_forward (Buffer *buffer, const char *str,
+                       View *view)
+{
+  buffer_search (buffer, str, view, TRUE);
+}
+
+static void
+buffer_search_backward (Buffer *buffer, const char *str,
+                        View *view)
+{
+  buffer_search (buffer, str, view, FALSE);
+}
+
 static void
 buffer_ref (Buffer *buffer)
 {